/*
 * FileExistOptionsPanel.java
 *
 * Created on December 6, 2007, 8:19 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */
package filecopier.gui.tabs;

import javax.swing.BoxLayout;
import javax.swing.JRadioButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.ButtonGroup;
import javax.swing.JTextField;
import javax.swing.JOptionPane;
import java.util.Calendar;
import java.awt.Dimension;
import javax.swing.event.DocumentListener;
import javax.swing.event.DocumentEvent;
import java.util.Calendar;
import java.util.TimeZone;
import java.util.SimpleTimeZone;
import java.util.IllegalFormatException;
import filecopier.options.Options;
import filecopier.options.RenameFmtString;
import filecopier.Singleton;
import filecopier.ActionCommand;
import filecopier.gui.Utilities;

/**
 *
 * @author david
 */
public class FileExistOptionsPanel extends javax.swing.JPanel implements DocumentListener, ActionCommand {

    private Boolean useGMT = null;
    private ButtonGroup buttonGrp = null;
    private JRadioButton autoRenameBtn = null;
    private JRadioButton manualRenameBtn = null;
    private JRadioButton overwriteBtn = null;
    private JRadioButton skipBtn = null;
    private JCheckBox restoreScriptChk = null;
    private JCheckBox overwritePromptChk = null;
    private JCheckBox updateOnlyChk = null;
    private JTextField fmtField = null;
    private JLabel fmtPreview = null;
    private JCheckBox gmtChkBox = null;
    private String fmtString = null;
    private boolean validFmt = false;
    private Calendar cal = null;
    private Options options = null;
    private Options.RenameType renameType = null;

    /**
     * Creates a new instance of FileExistOptionsPanel
     */
    public FileExistOptionsPanel() {
        super();
        initialize();
    }

    private void initialize() {
        this.options = Singleton.getInstance().getOptions();
        this.renameType = options.getRenameType();
        this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
        /* Create the check boxes. I must do this before creating the radio boxes because the radio boxes have action listeners
        that can change the status of the check boxes. Therefore, they must exist before I can do this. */
        initRestoreScriptChk();
        initOverwritePromptChk();
        initUpdateOnlyChk();

        // Add the buttons to the panel and the button group.
        add(initAutoRenameBtn());
        add(initManualRenameBtn());
        add(initOverwriteBtn());
        add(initSkipBtn());
        initButtonGrp();

        // Add a separator.
        add(new javax.swing.JSeparator());

        // Add the check boxes.
        add(restoreScriptChk);
        add(overwritePromptChk);
        add(updateOnlyChk);

        // Add another separator.
        add(new javax.swing.JSeparator());

        add(new JLabel("Rename Suffix Formatter:"));
        add(initFormatField());
        add(initFormatPreview());
        add(initGMTCheckBox());

        // Enable/disable the check buttons based on which radio button is selected.
        if (overwriteBtn.isSelected()) {
            overwritePromptChk.setEnabled(true);
            restoreScriptChk.setEnabled(false);
            updateOnlyChk.setEnabled(true);
        } else if (skipBtn.isSelected()) {
            overwritePromptChk.setEnabled(false);
            restoreScriptChk.setEnabled(false);
            updateOnlyChk.setEnabled(false);
        } else {
            overwritePromptChk.setEnabled(false);
            restoreScriptChk.setEnabled(true);
            updateOnlyChk.setEnabled(true);
        }
    }

    /**
     * This method initializes restoreScriptChk 
     *  
     * @return javax.swing.JCheckBox    
     */
    private JCheckBox initRestoreScriptChk() {
        if (restoreScriptChk == null) {
            restoreScriptChk = new JCheckBox("Build Restore Script");
            restoreScriptChk.setMnemonic(java.awt.event.KeyEvent.VK_B);
            restoreScriptChk.setToolTipText("Build a restore script to reverse the copy operation.");
            restoreScriptChk.setSelected(options.buildRestoreScript());

            restoreScriptChk.addActionListener(new java.awt.event.ActionListener() {

                public void actionPerformed(java.awt.event.ActionEvent e) {
                    options.setBuildRestoreScript(!options.buildRestoreScript());
                }
            });
        }
        return restoreScriptChk;
    }

    private JCheckBox initOverwritePromptChk() {
        if (overwritePromptChk == null) {
            overwritePromptChk = new JCheckBox("Prompt Before Overwriting");
            overwritePromptChk.setMnemonic(java.awt.event.KeyEvent.VK_W);
            overwritePromptChk.setToolTipText("If destination file exists, confirm an overwrite.");
            overwritePromptChk.setSelected(options.promptForOverwrite());

            overwritePromptChk.addActionListener(new java.awt.event.ActionListener() {

                public void actionPerformed(java.awt.event.ActionEvent e) {
                    options.setPromptForOverwrite(!options.promptForOverwrite());
                }
            });
        }
        return overwritePromptChk;
    }

    private JCheckBox initUpdateOnlyChk() {
        if (updateOnlyChk == null) {
            updateOnlyChk = new JCheckBox("Update");
            updateOnlyChk.setMnemonic(java.awt.event.KeyEvent.VK_T);
            updateOnlyChk.setToolTipText("Rename/replace existing file only if destination file is older than its corresponding source file.");
            updateOnlyChk.setSelected(options.getUpdateOnly());

            updateOnlyChk.addActionListener(new java.awt.event.ActionListener() {

                public void actionPerformed(java.awt.event.ActionEvent e) {
                    options.setUpdateOnly(!options.getUpdateOnly());
                }
            });
        }
        return updateOnlyChk;
    }

    private JRadioButton initAutoRenameBtn() {
        if (autoRenameBtn == null) {
            autoRenameBtn = new JRadioButton("Rename Automatically");
            autoRenameBtn.setLocation(new java.awt.Point(4, 22));
            autoRenameBtn.setToolTipText("<html>Automatically rename files that exist. If Merge is selected, the contents of<br>" +
                    "existing directories will be merged and all existing regular files will be<br>" +
                    "renamed automatically. If Merge is not selected, existing files and directories<br>" +
                    "will be renamed automatically.</html>");

            autoRenameBtn.setMnemonic(java.awt.event.KeyEvent.VK_R);
            autoRenameBtn.setSelected(renameType == Options.RenameType.RenameAuto ? true : false);

            autoRenameBtn.addActionListener(new java.awt.event.ActionListener() {

                public void actionPerformed(java.awt.event.ActionEvent e) {
                    renameType = Options.RenameType.RenameAuto;
                    options.setRenameType(renameType);
                    overwritePromptChk.setEnabled(false);
                    restoreScriptChk.setEnabled(true);
                    updateOnlyChk.setEnabled(true);
                }
            });
        }
        return autoRenameBtn;
    }

    private JRadioButton initManualRenameBtn() {
        if (manualRenameBtn == null) {
            manualRenameBtn = new JRadioButton("Rename Manually");
            manualRenameBtn.setToolTipText("<html>Prompt for new name if files exist. If Merge is selected, the contents of<br>" +
                    "existing directories will be merged and all existing regular files will be<br>" +
                    "renamed manually. If Merge is not selected, existing files and directories<br>" +
                    "will be renamed manually.</html>");

            manualRenameBtn.setMnemonic(java.awt.event.KeyEvent.VK_Y);
            manualRenameBtn.setSelected(renameType == Options.RenameType.RenameManual ? true : false);

            manualRenameBtn.addActionListener(new java.awt.event.ActionListener() {

                public void actionPerformed(java.awt.event.ActionEvent e) {
                    renameType = Options.RenameType.RenameManual;
                    options.setRenameType(renameType);
                    overwritePromptChk.setEnabled(false);
                    restoreScriptChk.setEnabled(true);
                    updateOnlyChk.setEnabled(true);
                }
            });
        }
        return manualRenameBtn;
    }

    private JRadioButton initOverwriteBtn() {
        if (overwriteBtn == null) {
            overwriteBtn = new JRadioButton("Overwrite");
            overwriteBtn.setToolTipText("Overwrite files that exist. Directories will effectively be merged and all regular files will be overwritten.");
            overwriteBtn.setMnemonic(java.awt.event.KeyEvent.VK_O);
            overwriteBtn.setSelected(renameType == Options.RenameType.Overwrite ? true : false);

            overwriteBtn.addActionListener(new java.awt.event.ActionListener() {

                public void actionPerformed(java.awt.event.ActionEvent e) {
                    renameType = Options.RenameType.Overwrite;
                    options.setRenameType(renameType);
                    overwritePromptChk.setEnabled(true);
                    restoreScriptChk.setEnabled(false);
                    updateOnlyChk.setEnabled(true);
                }
            });
        }
        return overwriteBtn;
    }

    private JRadioButton initSkipBtn() {
        if (skipBtn == null) {
            skipBtn = new JRadioButton("Skip");
            skipBtn.setToolTipText("Skip files that exist. Directories will not be skipped if Merge is selected.");
            skipBtn.setMnemonic(java.awt.event.KeyEvent.VK_K);
            skipBtn.setSelected(renameType == Options.RenameType.Skip ? true : false);

            skipBtn.addActionListener(new java.awt.event.ActionListener() {

                public void actionPerformed(java.awt.event.ActionEvent e) {
                    renameType = Options.RenameType.Skip;
                    options.setRenameType(renameType);
                    overwritePromptChk.setEnabled(false);
                    restoreScriptChk.setEnabled(false);
                    updateOnlyChk.setEnabled(false);
                }
            });
        }
        return skipBtn;
    }

    private ButtonGroup initButtonGrp() {
        if (buttonGrp == null) {
            buttonGrp = new ButtonGroup();
            buttonGrp.add(autoRenameBtn);
            buttonGrp.add(manualRenameBtn);
            buttonGrp.add(overwriteBtn);
            buttonGrp.add(skipBtn);
        }
        return buttonGrp;
    }

    private JTextField initFormatField() {
        if (fmtField == null) {
            fmtField = new JTextField();
            fmtField.setToolTipText("<html>FileCopier appends a format of the last modified date to renamed files. Type in<br>" +
                    "your desired format. For help on how to build valid formats, click the Help button<br>" +
                    "and go to the \"Rename Options\" section</html>");

            Dimension preferredSize = fmtField.getPreferredSize();
            fmtField.setMaximumSize(new Dimension(Short.MAX_VALUE, preferredSize.height));
            fmtField.setText(options.getRenameFmtString().getRenameFmtString());

            fmtField.getDocument().addDocumentListener(this);
            fmtField.setComponentPopupMenu(Utilities.createEditPopupMenu(fmtField));
        }
        return fmtField;
    }

    private JLabel initFormatPreview() {
        if (fmtPreview == null) {
            fmtPreview = new JLabel();
            fmtPreview.setText(options.getRenameFmtString().getPreviewRenameFmtString());
        }
        return (fmtPreview);
    }

    private JCheckBox initGMTCheckBox() {
        if (gmtChkBox == null) {
            gmtChkBox = new JCheckBox("Use GMT");
            gmtChkBox.setMnemonic(java.awt.event.KeyEvent.VK_G);
            gmtChkBox.setToolTipText("Convert last modified date time to Greenwich mean time.");
            useGMT = options.getUseGMT();
            gmtChkBox.setSelected(useGMT);
            cal = useGMT ? Calendar.getInstance(new SimpleTimeZone(0, "GMT")) : Calendar.getInstance();

            gmtChkBox.addActionListener(new java.awt.event.ActionListener() {

                public void actionPerformed(java.awt.event.ActionEvent e) {
                    boolean gmtSelected = gmtChkBox.isSelected();
                    options.setUseGMT(gmtSelected);
                    useGMT = gmtSelected;

                    TimeZone timeZone = gmtSelected ? new SimpleTimeZone(0, "GMT") : TimeZone.getDefault();

                    RenameFmtString renameFmtString = options.getRenameFmtString();
                    renameFmtString.validateRenameFmtString(timeZone);
                    fmtPreview.setText(renameFmtString.getPreviewRenameFmtString());
                }
            });

        }
        return (gmtChkBox);
    }

    public boolean chkFmtString() {
        boolean isValid = false;
        String msg = null;

        if (!validFmt) {
            msg = fmtString + " is not a valid format string. Do you want to use the default format string or correct the " +
                    "format string you entered?";
        } else {
            if (fmtPreview.toString().contains(":")) {
                msg = fmtString + " is a valid format string, but it will produce ':' characters which cannot be used in a " +
                        "filename. Do you want to use the default format string or correct the format string you entered?";
            } else if (fmtString.equals("")) {
                msg = "Rename format string is empty. Do you want to use the default format string or correct the format string " +
                        "you entered?";
            } else {
                isValid = true;
            }
        }

        if (msg != null) {
            Object[] possibleValues = {"Use default", "Fix format string"};
            int val = JOptionPane.showOptionDialog(null, msg, "Rename Format String Issue", JOptionPane.YES_NO_OPTION,
                    JOptionPane.QUESTION_MESSAGE, null, possibleValues, possibleValues[0]);

            if (val != JOptionPane.CLOSED_OPTION) {
                if (val == JOptionPane.YES_OPTION) {
                //fmtString = OptionsOrig.defaultRenameFmtStr;
                //fmtField.setText(fmtString);
                //isValid = true;
                }
            }
        }

        return isValid;
    }

    public void changedUpdate(DocumentEvent e) {
    }

    public void insertUpdate(DocumentEvent e) {
        setFormat();
    }

    public void removeUpdate(DocumentEvent e) {
        setFormat();
    }

    private void setFormat() {
        if (cal == null) {
            if (gmtChkBox.isSelected()) {
                cal = Calendar.getInstance(new SimpleTimeZone(0, "GMT"));
            } else {
                cal = Calendar.getInstance();
            }
        }
        fmtString = fmtField.getText();
        RenameFmtString renameFmtString = options.getRenameFmtString();
        String origFmtString = renameFmtString.getRenameFmtString();

        try {
            renameFmtString.setRenameFmtString(fmtField.getText());
            fmtPreview.setText(renameFmtString.getPreviewRenameFmtString());
        } catch (IllegalFormatException e) {
            // Set the renameFmtString back to what it was before because this one is invalid.
            renameFmtString.setRenameFmtString(origFmtString);
            // It's better to just swallow this exception because all it means is that the user changed the format string in
            // a way that makes it invalid. If the user deletes a character one at a time and I logged it, the log file could
            // grow quickly if I logged each stack trace. Before trying a copy operation, the user will be warned that it is
            // an invalid format string.
        }
    }

    public void doAction() {
        // Set all values to their defaults.
        if (restoreScriptChk.isSelected() != Options.defaultBuildRestoreScript) {
            restoreScriptChk.doClick();
        }
        if (overwritePromptChk.isSelected() != Options.defaultPromptForOverwrite) {
            overwritePromptChk.doClick();
        }
        if (updateOnlyChk.isSelected() != Options.defaultUpdateOnly) {
            updateOnlyChk.doClick();
        }
        if (gmtChkBox.isSelected() != Options.defaultUseGMT) {
            gmtChkBox.doClick();
        }
        if (!fmtField.getText().equals(Options.defaultRenameFmtStr)) {
            fmtField.setText(Options.defaultRenameFmtStr);
        }
        autoRenameBtn.doClick();
    }
}
